package com.zenithmind.document.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.document.mapper.DocumentMapper;
import com.zenithmind.document.pojo.domain.Document;
import com.zenithmind.document.pojo.dto.DocumentCreateDTO;
import com.zenithmind.document.pojo.dto.DocumentUpdateDTO;
import com.zenithmind.document.pojo.dto.DocumentUploadDTO;
import com.zenithmind.document.pojo.query.DocumentQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentDetailVO;
import com.zenithmind.document.pojo.vo.DocumentStatisticsVO;
import com.zenithmind.document.pojo.vo.DocumentVO;
import com.zenithmind.document.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 文档服务门面实现类
 *
 * 违反原则分析：
 * ❌ 单一职责原则：承担了过多职责（CRUD、搜索、处理、统计）
 * ❌ 接口隔离原则：实现了过于庞大的接口
 * ⚠️ 依赖倒置原则：部分方法直接依赖Mapper
 *
 * 修复建议：
 * 1. 拆分为多个专门的服务实现
 * 2. 使用组合模式而非继承
 * 3. 引入抽象层隔离Mapper依赖
 *
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@Primary
@RequiredArgsConstructor
public class DocumentServiceImpl extends ServiceImpl<DocumentMapper, Document> implements DocumentService {

    private final DocumentBasicService documentBasicService;
    private final DocumentSearchService documentSearchService;
    private final DocumentProcessService documentProcessService;
    private final DocumentStatisticsService documentStatisticsService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentVO uploadDocument(DocumentUploadDTO uploadDTO) {
        log.info("上传文档: {}", uploadDTO.getFile().getOriginalFilename());

        try {
            // 1. 验证文件
            validateUploadFile(uploadDTO.getFile());

            // 2. 创建文档实体
            Document document = createDocumentFromUpload(uploadDTO);

            // 3. 保存文档信息到数据库
            save(document);

            // 4. 异步处理文件存储和内容提取
            processDocumentAsync(document, uploadDTO.getFile());

            // 5. 转换为VO返回
            return convertToVO(document);

        } catch (Exception e) {
            log.error("文档上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文档上传失败: " + e.getMessage());
        }
    }

    /**
     * 验证上传文件
     */
    private void validateUploadFile(org.springframework.web.multipart.MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        // 检查文件大小 (100MB限制)
        long maxSize = 100 * 1024 * 1024L;
        if (file.getSize() > maxSize) {
            throw new IllegalArgumentException("文件大小不能超过100MB");
        }

        // 检查文件类型
        String filename = file.getOriginalFilename();
        if (filename == null || !isSupportedFileType(filename)) {
            throw new IllegalArgumentException("不支持的文件类型");
        }
    }

    /**
     * 检查是否为支持的文件类型
     */
    private boolean isSupportedFileType(String filename) {
        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
        String[] supportedTypes = {"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx",
            "txt", "md", "html", "xml", "json", "csv", "rtf", "odt", "ods", "odp"};
        return java.util.Arrays.asList(supportedTypes).contains(extension);
    }

    /**
     * 从上传信息创建文档实体
     */
    private Document createDocumentFromUpload(DocumentUploadDTO uploadDTO) {
        String userId = UserContext.getUserId();
        String filename = uploadDTO.getFile().getOriginalFilename();
        String fileType = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();

        Document document = Document.create(
            filename,
            uploadDTO.getTitle() != null ? uploadDTO.getTitle() : filename,
            fileType,
            uploadDTO.getCategoryId(),
            userId
        );

        // 设置文件相关信息
        document.setOriginalName(filename);
        document.setFileSize(uploadDTO.getFile().getSize());
        document.setMimeType(uploadDTO.getFile().getContentType());
        document.setSource(com.zenithmind.document.pojo.domain.Document.DocumentSource.UPLOAD.getCode());

        if (uploadDTO.getDescription() != null) {
            document.setDescription(uploadDTO.getDescription());
        }

        return document;
    }

    /**
     * 异步处理文档
     */
    private void processDocumentAsync(Document document, org.springframework.web.multipart.MultipartFile file) {
        // 这里应该使用异步任务处理，暂时同步处理
        try {
            // 1. 文件存储 (模拟)
            String filePath = storeFile(document.getId(), file);
            document.setFilePath(filePath);

            // 2. 内容提取 (模拟)
            String content = extractContent(file);
            document.setContent(content);

            // 3. 生成摘要 (模拟)
            String summary = generateSummary(content);
            document.setSummary(summary);

            // 4. 更新文档状态
            document.setStatus(com.zenithmind.document.pojo.domain.Document.DocumentStatus.NORMAL.getCode());
            updateById(document);

        } catch (Exception e) {
            log.error("文档处理失败: documentId={}, error={}", document.getId(), e.getMessage());
            document.setStatus(com.zenithmind.document.pojo.domain.Document.DocumentStatus.FAILED.getCode());
            updateById(document);
        }
    }

    /**
     * 存储文件 (模拟实现)
     */
    private String storeFile(String documentId, org.springframework.web.multipart.MultipartFile file) {
        // 模拟文件存储路径
        return "/documents/" + documentId + "/" + file.getOriginalFilename();
    }

    /**
     * 提取文件内容 (模拟实现)
     */
    private String extractContent(org.springframework.web.multipart.MultipartFile file) {
        // 模拟内容提取
        return "提取的文档内容: " + file.getOriginalFilename();
    }

    /**
     * 生成摘要 (模拟实现)
     */
    private String generateSummary(String content) {
        if (content == null || content.length() <= 100) {
            return content;
        }
        return content.substring(0, 100) + "...";
    }

    /**
     * 模拟文件下载 (模拟实现)
     */
    private byte[] simulateFileDownload(Document document) {
        // 模拟文件内容
        String content = "模拟文件内容: " + document.getName();
        return content.getBytes(java.nio.charset.StandardCharsets.UTF_8);
    }

    /**
     * 生成预览URL (模拟实现)
     */
    private String generatePreviewUrl(Document document) {
        // 模拟预览URL生成
        return "/api/v1/documents/" + document.getId() + "/preview?type=" + document.getType();
    }

    /**
     * 检查是否为支持的目标格式
     */
    private boolean isSupportedTargetFormat(String targetFormat) {
        String[] supportedFormats = {"pdf", "doc", "docx", "txt", "html", "md", "rtf"};
        return java.util.Arrays.asList(supportedFormats).contains(targetFormat.toLowerCase());
    }

    /**
     * 执行文档格式转换 (模拟实现)
     */
    private String performDocumentConversion(Document document, String targetFormat, String userId) {
        // 模拟创建转换后的文档
        Document convertedDoc = Document.create(
            document.getName() + "_converted." + targetFormat,
            document.getTitle() + " (转换为" + targetFormat.toUpperCase() + ")",
            targetFormat,
            document.getCategoryId(),
            userId
        );

        convertedDoc.setParentId(document.getId());
        convertedDoc.setSource(Document.DocumentSource.CONVERT.getCode());
        convertedDoc.setContent("转换后的文档内容: " + document.getName());

        save(convertedDoc);
        return convertedDoc.getId();
    }

    /**
     * 执行内容提取 (模拟实现)
     */
    private String performContentExtraction(Document document) {
        // 模拟根据文件类型提取内容
        String fileType = document.getType().toLowerCase();
        switch (fileType) {
            case "pdf":
                return "从PDF文档提取的文本内容: " + document.getName();
            case "doc":
            case "docx":
                return "从Word文档提取的文本内容: " + document.getName();
            case "txt":
                return "纯文本文档内容: " + document.getName();
            default:
                return "从" + fileType.toUpperCase() + "文档提取的内容: " + document.getName();
        }
    }

    /**
     * 执行摘要生成 (模拟实现)
     */
    private String performSummaryGeneration(String content) {
        if (content == null || content.trim().isEmpty()) {
            return "无内容可生成摘要";
        }

        // 简单的摘要生成逻辑
        String[] sentences = content.split("[。！？.!?]");
        StringBuilder summary = new StringBuilder();

        int maxSentences = Math.min(3, sentences.length);
        for (int i = 0; i < maxSentences; i++) {
            if (sentences[i].trim().length() > 10) {
                summary.append(sentences[i].trim()).append("。");
            }
        }

        if (summary.length() == 0) {
            // 如果没有合适的句子，取前100个字符
            return content.length() > 100 ? content.substring(0, 100) + "..." : content;
        }

        return summary.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentVO createDocument(DocumentCreateDTO createDTO) {
        log.info("创建文档: {}", createDTO.getName());
        
        Document document = new Document();
        BeanUtils.copyProperties(createDTO, document);
        document.setCreatorId(UserContext.getUserId());
        document.setCreateTime(LocalDateTime.now());
        document.setUpdateTime(LocalDateTime.now());
        
        save(document);
        
        return convertToVO(document);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDocument(String id, DocumentUpdateDTO updateDTO) {
        log.info("更新文档: {}", id);
        
        Document document = getById(id);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }
        
        BeanUtils.copyProperties(updateDTO, document);
        document.setLastModifierId(UserContext.getUserId());
        document.setUpdateTime(LocalDateTime.now());
        
        return updateById(document);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDocument(String id) {
        log.info("删除文档: {}", id);
        
        Document document = getById(id);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }
        
        document.setStatus(2); // 已删除
        document.setUpdateTime(LocalDateTime.now());
        
        return updateById(document);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteDocuments(List<String> ids) {
        log.info("批量删除文档: {}", ids);
        
        return baseMapper.batchUpdateDocumentStatus(ids, 2) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean restoreDocument(String id) {
        log.info("恢复文档: {}", id);
        
        Document document = getById(id);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }
        
        document.setStatus(1); // 正常
        document.setUpdateTime(LocalDateTime.now());
        
        return updateById(document);
    }

    @Override
    public IPage<DocumentVO> getDocumentPage(DocumentQueryDTO queryDTO) {
        log.info("分页查询文档");
        
        Page<DocumentVO> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        String userId = UserContext.getUserId();
        
        return baseMapper.selectDocumentPageWithDetails(page, queryDTO, userId);
    }

    @Override
    public DocumentDetailVO getDocumentDetail(String id, String userId) {
        log.info("获取文档详情: id={}, userId={}", id, userId);
        
        // 记录访问
        recordDocumentAccess(id, userId, "view");
        
        return baseMapper.selectDocumentDetailWithUser(id, userId);
    }

    @Override
    public List<DocumentVO> searchDocuments(String keyword, String userId, Integer limit) {
        log.info("搜索文档: keyword={}, userId={}", keyword, userId);
        
        return baseMapper.searchDocuments(keyword, userId, limit);
    }

    @Override
    public List<DocumentVO> fullTextSearchDocuments(String searchText, String userId, Integer limit) {
        log.info("全文搜索文档: searchText={}, userId={}", searchText, userId);
        
        return baseMapper.fullTextSearchDocuments(searchText, userId, limit);
    }

    @Override
    public List<DocumentVO> getUserDocuments(String userId, Integer limit) {
        log.info("获取用户文档: userId={}", userId);
        
        return baseMapper.selectUserDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getCategoryDocuments(String categoryId, String userId, Integer limit) {
        log.info("获取分类文档: categoryId={}, userId={}", categoryId, userId);
        
        return baseMapper.selectCategoryDocuments(categoryId, userId, limit);
    }

    @Override
    public List<DocumentVO> getHotDocuments(String userId, Integer limit) {
        log.info("获取热门文档: userId={}", userId);
        
        return baseMapper.selectHotDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getLatestDocuments(String userId, Integer limit) {
        log.info("获取最新文档: userId={}", userId);
        
        return baseMapper.selectLatestDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getRecommendedDocuments(String userId, Integer limit) {
        log.info("获取推荐文档: userId={}", userId);
        
        return baseMapper.selectRecommendedDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getRelatedDocuments(String documentId, String userId, Integer limit) {
        log.info("获取相关文档: documentId={}, userId={}", documentId, userId);
        
        return baseMapper.selectRelatedDocuments(documentId, userId, limit);
    }

    @Override
    public List<DocumentVO> getFavoriteDocuments(String userId, Integer limit) {
        log.info("获取收藏文档: userId={}", userId);
        
        return baseMapper.selectFavoriteDocuments(userId, limit);
    }

    @Override
    public List<DocumentVO> getRecentDocuments(String userId, Integer limit) {
        log.info("获取最近访问文档: userId={}", userId);
        
        return baseMapper.selectRecentDocuments(userId, limit);
    }

    @Override
    public byte[] downloadDocument(String id, String userId) {
        log.info("下载文档: id={}, userId={}", id, userId);
        
        // 检查权限
        if (!checkDocumentPermission(id, userId, "download")) {
            throw new RuntimeException("无下载权限");
        }
        
        // 记录下载
        recordDocumentAccess(id, userId, "download");

        // 实现文件下载逻辑
        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 模拟文件读取
            return simulateFileDownload(document);

        } catch (Exception e) {
            log.error("文档下载失败: id={}, userId={}, error={}", id, userId, e.getMessage());
            throw new RuntimeException("文档下载失败: " + e.getMessage());
        }
    }

    @Override
    public String previewDocument(String id, String userId) {
        log.info("预览文档: id={}, userId={}", id, userId);
        
        // 检查权限
        if (!checkDocumentPermission(id, userId, "view")) {
            throw new RuntimeException("无查看权限");
        }
        
        // 记录访问
        recordDocumentAccess(id, userId, "preview");

        // 实现文档预览逻辑
        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 生成预览URL
            String previewUrl = generatePreviewUrl(document);

            // 更新预览URL到数据库
            if (previewUrl != null && !previewUrl.equals(document.getPreviewUrl())) {
                document.setPreviewUrl(previewUrl);
                updateById(document);
            }

            return previewUrl;

        } catch (Exception e) {
            log.error("文档预览失败: id={}, userId={}, error={}", id, userId, e.getMessage());
            throw new RuntimeException("文档预览失败: " + e.getMessage());
        }
    }

    @Override
    public String convertDocument(String id, String targetFormat, String userId) {
        log.info("转换文档格式: id={}, targetFormat={}, userId={}", id, targetFormat, userId);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 验证目标格式
            if (!isSupportedTargetFormat(targetFormat)) {
                throw new IllegalArgumentException("不支持的目标格式: " + targetFormat);
            }

            // 模拟格式转换
            String convertedDocumentId = performDocumentConversion(document, targetFormat, userId);

            log.info("文档格式转换完成: originalId={}, convertedId={}, targetFormat={}",
                id, convertedDocumentId, targetFormat);

            return convertedDocumentId;

        } catch (Exception e) {
            log.error("文档格式转换失败: id={}, targetFormat={}, error={}", id, targetFormat, e.getMessage());
            throw new RuntimeException("文档格式转换失败: " + e.getMessage());
        }
    }

    @Override
    public String extractDocumentContent(String id) {
        log.info("提取文档内容: {}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 如果已有内容，直接返回
            if (document.getContent() != null && !document.getContent().trim().isEmpty()) {
                return document.getContent();
            }

            // 模拟内容提取
            String extractedContent = performContentExtraction(document);

            // 更新文档内容
            document.setContent(extractedContent);
            updateById(document);

            return extractedContent;

        } catch (Exception e) {
            log.error("文档内容提取失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("文档内容提取失败: " + e.getMessage());
        }
    }

    @Override
    public String generateDocumentSummary(String id) {
        log.info("生成文档摘要: {}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 如果已有摘要，直接返回
            if (document.getSummary() != null && !document.getSummary().trim().isEmpty()) {
                return document.getSummary();
            }

            // 获取文档内容
            String content = document.getContent();
            if (content == null || content.trim().isEmpty()) {
                content = extractDocumentContent(id);
            }

            // 生成摘要
            String summary = performSummaryGeneration(content);

            // 更新文档摘要
            document.setSummary(summary);
            updateById(document);

            return summary;

        } catch (Exception e) {
            log.error("文档摘要生成失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("文档摘要生成失败: " + e.getMessage());
        }
    }

    @Override
    public Boolean checkDocumentPermission(String documentId, String userId, String permission) {
        log.info("检查文档权限: documentId={}, userId={}, permission={}", documentId, userId, permission);
        
        return baseMapper.checkDocumentPermission(documentId, userId, permission);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean favoriteDocument(String documentId, String userId) {
        log.info("收藏文档: documentId={}, userId={}", documentId, userId);
        
        return baseMapper.favoriteDocument(documentId, userId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unfavoriteDocument(String documentId, String userId) {
        log.info("取消收藏文档: documentId={}, userId={}", documentId, userId);
        
        return baseMapper.unfavoriteDocument(documentId, userId) > 0;
    }

    @Override
    public DocumentVO copyDocument(String sourceDocumentId, String newName, String userId) {
        log.info("复制文档: sourceDocumentId={}, newName={}, userId={}", sourceDocumentId, newName, userId);
        
        String newDocumentId = baseMapper.copyDocument(sourceDocumentId, newName, userId);
        Document newDocument = getById(newDocumentId);
        
        return convertToVO(newDocument);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean moveDocuments(List<String> documentIds, String categoryId) {
        log.info("移动文档: documentIds={}, categoryId={}", documentIds, categoryId);
        
        return baseMapper.batchMoveDocuments(documentIds, categoryId) > 0;
    }

    @Override
    public List<DocumentVO> getDocumentVersions(String documentId) {
        log.info("获取文档版本列表: documentId={}", documentId);
        
        return baseMapper.selectDocumentVersions(documentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createDocumentVersion(String documentId, String description, String userId) {
        log.info("创建文档版本: documentId={}, description={}, userId={}", documentId, description, userId);
        
        // 生成版本号
        String versionNumber = generateVersionNumber(documentId);
        
        return baseMapper.createDocumentVersion(documentId, versionNumber, description, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean restoreDocumentVersion(String documentId, String versionId, String userId) {
        log.info("恢复文档版本: documentId={}, versionId={}, userId={}", documentId, versionId, userId);
        
        return baseMapper.restoreDocumentVersion(documentId, versionId, userId) > 0;
    }

    @Override
    public DocumentStatisticsVO getDocumentStatistics(String documentId) {
        log.info("获取文档统计信息: documentId={}", documentId);
        
        return baseMapper.selectDocumentStatistics(documentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean recordDocumentAccess(String documentId, String userId, String accessType) {
        log.info("记录文档访问: documentId={}, userId={}, accessType={}", documentId, userId, accessType);
        
        // 更新统计
        baseMapper.updateDocumentStatistics(documentId, accessType);
        
        // 记录访问日志
        return baseMapper.recordDocumentAccess(documentId, userId, accessType, null, null) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanupExpiredDocuments() {
        log.info("清理过期文档");
        
        return baseMapper.cleanupExpiredDocuments(LocalDateTime.now());
    }

    @Override
    public DocumentStatisticsVO getDocumentStorageStatistics(String userId) {
        log.info("获取文档存储统计: userId={}", userId);
        
        return baseMapper.selectDocumentStorageStatistics(userId);
    }

    /**
     * 转换为VO
     */
    private DocumentVO convertToVO(Document document) {
        DocumentVO vo = new DocumentVO();
        BeanUtils.copyProperties(document, vo);

        // 补充其他字段转换
        if (document.getDocumentStatus() != null) {
            vo.setStatusName(document.getDocumentStatus().getDescription());
        }

        if (document.getAccessLevelEnum() != null) {
            vo.setAccessLevelName(document.getAccessLevelEnum().getDescription());
        }

        // 格式化文件大小
        vo.setFileSizeFormatted(document.getFormattedFileSize());

        // 设置是否为最新版本
        vo.setIsLatest(document.isLatestVersion());

        // 处理标签 (从JSON字符串转换为列表)
        if (document.getTags() != null && !document.getTags().trim().isEmpty()) {
            try {
                // 简单的JSON解析，实际项目中应使用JSON库
                String[] tagArray = document.getTags().replace("[", "").replace("]", "")
                    .replace("\"", "").split(",");
                vo.setTags(java.util.Arrays.asList(tagArray));
            } catch (Exception e) {
                log.warn("解析文档标签失败: documentId={}, tags={}", document.getId(), document.getTags());
                vo.setTags(new java.util.ArrayList<>());
            }
        } else {
            vo.setTags(new java.util.ArrayList<>());
        }

        // 处理关键词 (从字符串转换为列表)
        if (document.getKeywords() != null && !document.getKeywords().trim().isEmpty()) {
            String[] keywordArray = document.getKeywords().split(",");
            vo.setKeywords(java.util.Arrays.asList(keywordArray));
        } else {
            vo.setKeywords(new java.util.ArrayList<>());
        }

        return vo;
    }

    /**
     * 生成版本号
     */
    private String generateVersionNumber(String documentId) {
        try {
            // 查询当前文档的最高版本号
            Document document = getById(documentId);
            if (document == null) {
                return "1.0";
            }

            // 查询同一父文档的所有版本
            String parentId = document.getParentId() != null ? document.getParentId() : documentId;

            // 模拟查询版本号逻辑
            // 实际实现中应该查询数据库获取最大版本号
            String currentVersion = document.getVersion();
            if (currentVersion == null || currentVersion.trim().isEmpty()) {
                return "1.0";
            }

            // 解析版本号并递增
            return incrementVersion(currentVersion);

        } catch (Exception e) {
            log.warn("生成版本号失败，使用默认版本号: documentId={}, error={}", documentId, e.getMessage());
            return "1.0";
        }
    }

    /**
     * 递增版本号
     */
    private String incrementVersion(String currentVersion) {
        try {
            String[] parts = currentVersion.split("\\.");
            if (parts.length >= 2) {
                int major = Integer.parseInt(parts[0]);
                int minor = Integer.parseInt(parts[1]);
                minor++;
                return major + "." + minor;
            } else if (parts.length == 1) {
                int version = Integer.parseInt(parts[0]);
                version++;
                return version + ".0";
            }
        } catch (NumberFormatException e) {
            log.warn("解析版本号失败: currentVersion={}", currentVersion);
        }

        return "1.0";
    }

    /**
     * 执行文档修复 (模拟实现)
     */
    private boolean performDocumentRepair(Document document) {
        // 模拟文档修复逻辑
        log.info("开始修复文档: id={}, name={}", document.getId(), document.getName());

        // 检查文件是否存在
        if (document.getFilePath() == null || document.getFilePath().trim().isEmpty()) {
            log.warn("文档文件路径为空，修复失败: id={}", document.getId());
            return false;
        }

        // 模拟文件完整性检查
        boolean fileIntegrityOk = checkFileIntegrity(document);
        if (!fileIntegrityOk) {
            log.warn("文档文件完整性检查失败: id={}", document.getId());
            return false;
        }

        // 模拟重新提取内容
        try {
            String content = performContentExtraction(document);
            document.setContent(content);

            String summary = performSummaryGeneration(content);
            document.setSummary(summary);

            log.info("文档修复成功: id={}", document.getId());
            return true;
        } catch (Exception e) {
            log.error("文档修复过程中发生错误: id={}, error={}", document.getId(), e.getMessage());
            return false;
        }
    }

    /**
     * 检查文件完整性 (模拟实现)
     */
    private boolean checkFileIntegrity(Document document) {
        // 模拟文件完整性检查
        return document.getFileSize() != null && document.getFileSize() > 0;
    }

    /**
     * 执行文档验证 (模拟实现)
     */
    private boolean performDocumentValidation(Document document) {
        // 基本信息验证
        if (!document.isBasicInfoComplete()) {
            log.warn("文档基本信息不完整: id={}", document.getId());
            return false;
        }

        // 文件完整性验证
        if (!checkFileIntegrity(document)) {
            log.warn("文档文件完整性验证失败: id={}", document.getId());
            return false;
        }

        // 权限配置验证
        if (document.getAccessLevel() == null) {
            log.warn("文档访问权限未设置: id={}", document.getId());
            return false;
        }

        // 状态验证
        if (document.getStatus() == null) {
            log.warn("文档状态未设置: id={}", document.getId());
            return false;
        }

        log.info("文档验证通过: id={}", document.getId());
        return true;
    }

    /**
     * 检查文档类型是否支持OCR
     */
    private boolean isSupportedForOCR(String fileType) {
        String[] ocrSupportedTypes = {"pdf", "jpg", "jpeg", "png", "bmp", "tiff", "gif"};
        return java.util.Arrays.asList(ocrSupportedTypes).contains(fileType.toLowerCase());
    }

    /**
     * 执行OCR处理 (模拟实现)
     */
    private String performOCRProcessing(Document document) {
        // 模拟OCR处理
        String fileType = document.getType().toLowerCase();
        switch (fileType) {
            case "pdf":
                return "从PDF文档OCR识别的文本内容: " + document.getName();
            case "jpg":
            case "jpeg":
            case "png":
            case "bmp":
            case "tiff":
            case "gif":
                return "从图片OCR识别的文本内容: " + document.getName();
            default:
                return "OCR识别的文本内容: " + document.getName();
        }
    }

    /**
     * 执行文档拆分 (模拟实现)
     */
    private List<String> performDocumentSplit(Document document, String splitRule, String userId) {
        List<String> splitDocumentIds = new java.util.ArrayList<>();

        // 根据拆分规则进行拆分
        switch (splitRule.toLowerCase()) {
            case "page":
                // 按页拆分
                splitDocumentIds = splitByPage(document, userId);
                break;
            case "chapter":
                // 按章节拆分
                splitDocumentIds = splitByChapter(document, userId);
                break;
            case "size":
                // 按大小拆分
                splitDocumentIds = splitBySize(document, userId);
                break;
            default:
                throw new IllegalArgumentException("不支持的拆分规则: " + splitRule);
        }

        return splitDocumentIds;
    }

    /**
     * 按页拆分文档 (模拟实现)
     */
    private List<String> splitByPage(Document document, String userId) {
        List<String> splitIds = new java.util.ArrayList<>();

        // 模拟拆分为3页
        for (int i = 1; i <= 3; i++) {
            Document splitDoc = Document.create(
                document.getName() + "_page_" + i + "." + document.getType(),
                document.getTitle() + " (第" + i + "页)",
                document.getType(),
                document.getCategoryId(),
                userId
            );

            splitDoc.setParentId(document.getId());
            splitDoc.setSource(Document.DocumentSource.CONVERT.getCode());
            splitDoc.setContent("第" + i + "页内容: " + document.getName());

            save(splitDoc);
            splitIds.add(splitDoc.getId());
        }

        return splitIds;
    }

    /**
     * 按章节拆分文档 (模拟实现)
     */
    private List<String> splitByChapter(Document document, String userId) {
        List<String> splitIds = new java.util.ArrayList<>();

        // 模拟拆分为2个章节
        for (int i = 1; i <= 2; i++) {
            Document splitDoc = Document.create(
                document.getName() + "_chapter_" + i + "." + document.getType(),
                document.getTitle() + " (第" + i + "章)",
                document.getType(),
                document.getCategoryId(),
                userId
            );

            splitDoc.setParentId(document.getId());
            splitDoc.setSource(Document.DocumentSource.CONVERT.getCode());
            splitDoc.setContent("第" + i + "章内容: " + document.getName());

            save(splitDoc);
            splitIds.add(splitDoc.getId());
        }

        return splitIds;
    }

    /**
     * 按大小拆分文档 (模拟实现)
     */
    private List<String> splitBySize(Document document, String userId) {
        List<String> splitIds = new java.util.ArrayList<>();

        // 模拟按大小拆分为2部分
        for (int i = 1; i <= 2; i++) {
            Document splitDoc = Document.create(
                document.getName() + "_part_" + i + "." + document.getType(),
                document.getTitle() + " (第" + i + "部分)",
                document.getType(),
                document.getCategoryId(),
                userId
            );

            splitDoc.setParentId(document.getId());
            splitDoc.setSource(Document.DocumentSource.CONVERT.getCode());
            splitDoc.setContent("第" + i + "部分内容: " + document.getName());

            save(splitDoc);
            splitIds.add(splitDoc.getId());
        }

        return splitIds;
    }

    /**
     * 执行文档合并 (模拟实现)
     */
    private String performDocumentMerge(List<Document> documents, String userId) {
        // 创建合并后的文档
        Document firstDoc = documents.get(0);
        Document mergedDoc = Document.create(
            "merged_" + firstDoc.getName(),
            "合并文档: " + firstDoc.getTitle(),
            firstDoc.getType(),
            firstDoc.getCategoryId(),
            userId
        );

        mergedDoc.setSource(Document.DocumentSource.CONVERT.getCode());

        // 合并内容
        StringBuilder mergedContent = new StringBuilder();
        for (int i = 0; i < documents.size(); i++) {
            Document doc = documents.get(i);
            mergedContent.append("=== 文档").append(i + 1).append(": ").append(doc.getName()).append(" ===\n");
            if (doc.getContent() != null) {
                mergedContent.append(doc.getContent());
            } else {
                mergedContent.append("文档内容: ").append(doc.getName());
            }
            mergedContent.append("\n\n");
        }

        mergedDoc.setContent(mergedContent.toString());
        mergedDoc.setSummary("合并了" + documents.size() + "个文档的内容");

        save(mergedDoc);
        return mergedDoc.getId();
    }

    /**
     * 检查文档类型是否支持水印
     */
    private boolean isSupportedForWatermark(String fileType) {
        String[] watermarkSupportedTypes = {"pdf", "doc", "docx", "ppt", "pptx", "jpg", "jpeg", "png"};
        return java.util.Arrays.asList(watermarkSupportedTypes).contains(fileType.toLowerCase());
    }

    /**
     * 执行添加水印 (模拟实现)
     */
    private boolean performAddWatermark(Document document, String watermarkText, String position) {
        // 模拟添加水印
        log.info("为文档添加水印: id={}, text={}, position={}",
            document.getId(), watermarkText, position);

        // 模拟水印添加成功
        return true;
    }

    /**
     * 执行文档解密 (模拟实现)
     */
    private boolean performDocumentDecryption(Document document, String password) {
        // 模拟密码验证
        // 实际实现中应该验证密码的正确性
        if (password.length() < 6) {
            log.warn("密码长度不足: documentId={}", document.getId());
            return false;
        }

        // 模拟解密过程
        log.info("文档解密成功: id={}", document.getId());
        return true;
    }

    /**
     * 执行文档加密 (模拟实现)
     */
    private boolean performDocumentEncryption(Document document, String password, String algorithm) {
        // 模拟加密过程
        log.info("开始加密文档: id={}, algorithm={}", document.getId(), algorithm);

        // 验证算法支持
        String[] supportedAlgorithms = {"AES", "DES", "RSA"};
        if (!java.util.Arrays.asList(supportedAlgorithms).contains(algorithm.toUpperCase())) {
            log.warn("不支持的加密算法: {}", algorithm);
            return false;
        }

        // 模拟加密成功
        return true;
    }

    /**
     * 检查文档类型是否支持压缩
     */
    private boolean isSupportedForCompression(String fileType) {
        String[] compressionSupportedTypes = {"pdf", "jpg", "jpeg", "png", "bmp", "tiff"};
        return java.util.Arrays.asList(compressionSupportedTypes).contains(fileType.toLowerCase());
    }

    /**
     * 执行文档压缩 (模拟实现)
     */
    private String performDocumentCompression(Document document, Integer quality) {
        // 创建压缩后的文档
        Document compressedDoc = Document.create(
            document.getName() + "_compressed." + document.getType(),
            document.getTitle() + " (压缩版)",
            document.getType(),
            document.getCategoryId(),
            document.getCreatorId()
        );

        compressedDoc.setParentId(document.getId());
        compressedDoc.setSource(Document.DocumentSource.CONVERT.getCode());
        compressedDoc.setContent(document.getContent());

        // 模拟压缩后文件大小减少
        if (document.getFileSize() != null) {
            long compressedSize = (long) (document.getFileSize() * (quality / 100.0));
            compressedDoc.setFileSize(compressedSize);
        }

        save(compressedDoc);
        return compressedDoc.getId();
    }

    /**
     * 执行缩略图生成 (模拟实现)
     */
    private String performThumbnailGeneration(Document document) {
        // 模拟缩略图URL生成
        return "/thumbnails/" + document.getId() + "_thumb.jpg";
    }

    /**
     * 执行预览生成 (模拟实现)
     */
    private String performPreviewGeneration(Document document) {
        // 模拟预览URL生成
        return "/previews/" + document.getId() + "_preview.html";
    }

    @Override
    public Boolean validateDocumentOwnership(String documentId, String userId) {
        return documentBasicService.validateDocumentOwnership(documentId, userId);
    }

    @Override
    public Boolean existsDocument(String id) {
        return documentBasicService.existsDocument(id);
    }

    @Override
    public DocumentVO getDocumentById(String id) {
        return documentBasicService.getDocumentById(id);
    }

    @Override
    public List<DocumentVO> getDocumentsByCategory(String categoryId, String userId, Integer limit) {
        log.info("根据分类获取文档: categoryId={}, userId={}, limit={}", categoryId, userId, limit);

        try {
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Document> wrapper =
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();

            wrapper.eq("category_id", categoryId)
                   .eq("status", Document.DocumentStatus.NORMAL.getCode())
                   .orderByDesc("create_time");

            if (limit != null && limit > 0) {
                wrapper.last("LIMIT " + limit);
            }

            List<Document> documents = list(wrapper);
            return documents.stream()
                .filter(doc -> checkDocumentPermission(doc.getId(), userId, "view"))
                .map(this::convertToVO)
                .collect(java.util.stream.Collectors.toList());

        } catch (Exception e) {
            log.error("根据分类获取文档失败: categoryId={}, error={}", categoryId, e.getMessage());
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<DocumentVO> getHotDocuments(Integer limit) {
        log.info("获取热门文档: limit={}", limit);

        try {
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Document> wrapper =
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();

            wrapper.eq("status", Document.DocumentStatus.NORMAL.getCode())
                   .eq("access_level", Document.AccessLevel.PUBLIC.getCode())
                   .orderByDesc("view_count")
                   .orderByDesc("download_count")
                   .orderByDesc("create_time");

            if (limit != null && limit > 0) {
                wrapper.last("LIMIT " + limit);
            } else {
                wrapper.last("LIMIT 10"); // 默认限制10个
            }

            List<Document> documents = list(wrapper);
            return documents.stream()
                .map(this::convertToVO)
                .collect(java.util.stream.Collectors.toList());

        } catch (Exception e) {
            log.error("获取热门文档失败: error={}", e.getMessage());
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<DocumentVO> searchDocumentsByTags(List<String> tags, String userId, Integer limit) {
        log.info("按标签搜索文档: tags={}, userId={}, limit={}", tags, userId, limit);

        if (tags == null || tags.isEmpty()) {
            return new java.util.ArrayList<>();
        }

        try {
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Document> wrapper =
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();

            wrapper.eq("status", Document.DocumentStatus.NORMAL.getCode());

            // 构建标签查询条件
            for (String tag : tags) {
                wrapper.and(w -> w.like("tags", tag));
            }

            wrapper.orderByDesc("create_time");

            if (limit != null && limit > 0) {
                wrapper.last("LIMIT " + limit);
            }

            List<Document> documents = list(wrapper);
            return documents.stream()
                .filter(doc -> checkDocumentPermission(doc.getId(), userId, "view"))
                .map(this::convertToVO)
                .collect(java.util.stream.Collectors.toList());

        } catch (Exception e) {
            log.error("按标签搜索文档失败: tags={}, error={}", tags, e.getMessage());
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<DocumentVO> advancedSearchDocuments(String keyword, String categoryId, String type, String userId, Integer limit) {
        log.info("高级搜索文档: keyword={}, categoryId={}, type={}, userId={}, limit={}", keyword, categoryId, type, userId, limit);

        try {
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<Document> wrapper =
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();

            wrapper.eq("status", Document.DocumentStatus.NORMAL.getCode());

            // 关键词搜索
            if (keyword != null && !keyword.trim().isEmpty()) {
                wrapper.and(w -> w.like("name", keyword)
                    .or().like("title", keyword)
                    .or().like("content", keyword)
                    .or().like("summary", keyword));
            }

            // 分类过滤
            if (categoryId != null && !categoryId.trim().isEmpty()) {
                wrapper.eq("category_id", categoryId);
            }

            // 类型过滤
            if (type != null && !type.trim().isEmpty()) {
                wrapper.eq("type", type);
            }

            wrapper.orderByDesc("create_time");

            if (limit != null && limit > 0) {
                wrapper.last("LIMIT " + limit);
            }

            List<Document> documents = list(wrapper);
            return documents.stream()
                .filter(doc -> checkDocumentPermission(doc.getId(), userId, "view"))
                .map(this::convertToVO)
                .collect(java.util.stream.Collectors.toList());

        } catch (Exception e) {
            log.error("高级搜索文档失败: keyword={}, error={}", keyword, e.getMessage());
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public Boolean repairDocument(String id) {
        log.info("修复文档: id={}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查文档状态
            if (document.getDocumentStatus() != Document.DocumentStatus.FAILED) {
                log.info("文档状态正常，无需修复: id={}, status={}", id, document.getStatus());
                return true;
            }

            // 执行修复操作
            boolean repaired = performDocumentRepair(document);

            if (repaired) {
                document.markAsNormal();
                updateById(document);
                log.info("文档修复成功: id={}", id);
            } else {
                log.warn("文档修复失败: id={}", id);
            }

            return repaired;

        } catch (Exception e) {
            log.error("文档修复过程中发生错误: id={}, error={}", id, e.getMessage());
            return false;
        }
    }

    @Override
    public Boolean validateDocument(String id) {
        log.info("验证文档: id={}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                log.warn("文档不存在: id={}", id);
                return false;
            }

            // 执行文档验证
            boolean isValid = performDocumentValidation(document);

            log.info("文档验证完成: id={}, valid={}", id, isValid);
            return isValid;

        } catch (Exception e) {
            log.error("文档验证过程中发生错误: id={}, error={}", id, e.getMessage());
            return false;
        }
    }

    @Override
    public String performOCR(String id) {
        log.info("执行OCR: id={}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查文档类型是否支持OCR
            if (!isSupportedForOCR(document.getType())) {
                throw new IllegalArgumentException("文档类型不支持OCR: " + document.getType());
            }

            // 执行OCR处理
            String ocrResult = performOCRProcessing(document);

            // 更新文档内容
            if (ocrResult != null && !ocrResult.trim().isEmpty()) {
                document.setContent(ocrResult);
                updateById(document);
            }

            log.info("OCR处理完成: id={}, contentLength={}", id,
                ocrResult != null ? ocrResult.length() : 0);

            return ocrResult;

        } catch (Exception e) {
            log.error("OCR处理失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("OCR处理失败: " + e.getMessage());
        }
    }

    @Override
    public List<String> splitDocument(String id, String splitRule, String userId) {
        log.info("拆分文档: id={}, splitRule={}, userId={}", id, splitRule, userId);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 验证拆分规则
            if (splitRule == null || splitRule.trim().isEmpty()) {
                throw new IllegalArgumentException("拆分规则不能为空");
            }

            // 执行文档拆分
            List<String> splitDocumentIds = performDocumentSplit(document, splitRule, userId);

            log.info("文档拆分完成: originalId={}, splitCount={}", id, splitDocumentIds.size());
            return splitDocumentIds;

        } catch (Exception e) {
            log.error("文档拆分失败: id={}, splitRule={}, error={}", id, splitRule, e.getMessage());
            throw new RuntimeException("文档拆分失败: " + e.getMessage());
        }
    }

    @Override
    public String mergeDocuments(List<String> documentIds, String userId) {
        log.info("合并文档: documentIds={}, userId={}", documentIds, userId);

        if (documentIds == null || documentIds.isEmpty()) {
            throw new IllegalArgumentException("文档ID列表不能为空");
        }

        try {
            // 验证所有文档都存在
            List<Document> documents = new java.util.ArrayList<>();
            for (String docId : documentIds) {
                Document doc = getById(docId);
                if (doc == null) {
                    throw new RuntimeException("文档不存在: " + docId);
                }
                documents.add(doc);
            }

            // 执行文档合并
            String mergedDocumentId = performDocumentMerge(documents, userId);

            log.info("文档合并完成: sourceIds={}, mergedId={}", documentIds, mergedDocumentId);
            return mergedDocumentId;

        } catch (Exception e) {
            log.error("文档合并失败: documentIds={}, error={}", documentIds, e.getMessage());
            throw new RuntimeException("文档合并失败: " + e.getMessage());
        }
    }

    @Override
    public Boolean addWatermark(String id, String watermarkText, String position) {
        log.info("添加水印: id={}, watermarkText={}, position={}", id, watermarkText, position);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 验证水印参数
            if (watermarkText == null || watermarkText.trim().isEmpty()) {
                throw new IllegalArgumentException("水印文本不能为空");
            }

            // 检查文档类型是否支持水印
            if (!isSupportedForWatermark(document.getType())) {
                throw new IllegalArgumentException("文档类型不支持水印: " + document.getType());
            }

            // 执行添加水印
            boolean success = performAddWatermark(document, watermarkText, position);

            if (success) {
                log.info("水印添加成功: id={}, watermarkText={}", id, watermarkText);
            } else {
                log.warn("水印添加失败: id={}", id);
            }

            return success;

        } catch (Exception e) {
            log.error("添加水印失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("添加水印失败: " + e.getMessage());
        }
    }

    @Override
    public Boolean decryptDocument(String id, String password) {
        log.info("解密文档: id={}, password={}", id, "***");

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查文档是否已加密
            if (!document.isEncrypted()) {
                log.info("文档未加密，无需解密: id={}", id);
                return true;
            }

            // 验证密码
            if (password == null || password.trim().isEmpty()) {
                throw new IllegalArgumentException("解密密码不能为空");
            }

            // 执行解密
            boolean success = performDocumentDecryption(document, password);

            if (success) {
                document.setIsEncrypted(0);
                document.setEncryptionAlgorithm(null);
                updateById(document);
                log.info("文档解密成功: id={}", id);
            } else {
                log.warn("文档解密失败: id={}", id);
            }

            return success;

        } catch (Exception e) {
            log.error("文档解密失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("文档解密失败: " + e.getMessage());
        }
    }

    @Override
    public Boolean encryptDocument(String id, String password, String algorithm) {
        log.info("加密文档: id={}, password={}, algorithm={}", id, "***", algorithm);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查文档是否已加密
            if (document.isEncrypted()) {
                log.info("文档已加密，无需重复加密: id={}", id);
                return true;
            }

            // 验证密码和算法
            if (password == null || password.trim().isEmpty()) {
                throw new IllegalArgumentException("加密密码不能为空");
            }

            if (algorithm == null || algorithm.trim().isEmpty()) {
                algorithm = "AES"; // 默认算法
            }

            // 执行加密
            boolean success = performDocumentEncryption(document, password, algorithm);

            if (success) {
                document.setIsEncrypted(1);
                document.setEncryptionAlgorithm(algorithm);
                updateById(document);
                log.info("文档加密成功: id={}, algorithm={}", id, algorithm);
            } else {
                log.warn("文档加密失败: id={}", id);
            }

            return success;

        } catch (Exception e) {
            log.error("文档加密失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("文档加密失败: " + e.getMessage());
        }
    }

    @Override
    public String compressDocument(String id, Integer quality) {
        log.info("压缩文档: id={}, quality={}", id, quality);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 验证压缩质量参数
            if (quality == null || quality < 1 || quality > 100) {
                quality = 80; // 默认压缩质量
            }

            // 检查文档类型是否支持压缩
            if (!isSupportedForCompression(document.getType())) {
                throw new IllegalArgumentException("文档类型不支持压缩: " + document.getType());
            }

            // 执行压缩
            String compressedDocumentId = performDocumentCompression(document, quality);

            log.info("文档压缩完成: originalId={}, compressedId={}, quality={}",
                id, compressedDocumentId, quality);

            return compressedDocumentId;

        } catch (Exception e) {
            log.error("文档压缩失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("文档压缩失败: " + e.getMessage());
        }
    }

    @Override
    public String generateDocumentThumbnail(String id) {
        log.info("生成文档缩略图: id={}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查是否已有缩略图
            if (document.getThumbnailUrl() != null && !document.getThumbnailUrl().trim().isEmpty()) {
                log.info("文档已有缩略图: id={}, url={}", id, document.getThumbnailUrl());
                return document.getThumbnailUrl();
            }

            // 生成缩略图
            String thumbnailUrl = performThumbnailGeneration(document);

            // 更新缩略图URL
            if (thumbnailUrl != null && !thumbnailUrl.trim().isEmpty()) {
                document.setThumbnailUrl(thumbnailUrl);
                updateById(document);
            }

            log.info("缩略图生成完成: id={}, url={}", id, thumbnailUrl);
            return thumbnailUrl;

        } catch (Exception e) {
            log.error("生成缩略图失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("生成缩略图失败: " + e.getMessage());
        }
    }

    @Override
    public String generateDocumentPreview(String id) {
        log.info("生成文档预览: id={}", id);

        try {
            Document document = getById(id);
            if (document == null) {
                throw new RuntimeException("文档不存在");
            }

            // 检查是否已有预览
            if (document.getPreviewUrl() != null && !document.getPreviewUrl().trim().isEmpty()) {
                log.info("文档已有预览: id={}, url={}", id, document.getPreviewUrl());
                return document.getPreviewUrl();
            }

            // 生成预览
            String previewUrl = performPreviewGeneration(document);

            // 更新预览URL
            if (previewUrl != null && !previewUrl.trim().isEmpty()) {
                document.setPreviewUrl(previewUrl);
                updateById(document);
            }

            log.info("预览生成完成: id={}, url={}", id, previewUrl);
            return previewUrl;

        } catch (Exception e) {
            log.error("生成预览失败: id={}, error={}", id, e.getMessage());
            throw new RuntimeException("生成预览失败: " + e.getMessage());
        }
    }

    // DocumentStatisticsService 方法实现 - 只添加缺失的方法
    @Override
    public Object getUserStatistics(String userId) {
        return documentStatisticsService.getUserStatistics(userId);
    }

    @Override
    public Object getCategoryStatistics(String categoryId) {
        return documentStatisticsService.getCategoryStatistics(categoryId);
    }

    @Override
    public Object getSystemStatistics() {
        return documentStatisticsService.getSystemStatistics();
    }

    @Override
    public Object getHotDocumentsStatistics(Integer limit) {
        return documentStatisticsService.getHotDocumentsStatistics(limit);
    }

    @Override
    public Object getAccessTrendStatistics(String documentId, Integer days) {
        return documentStatisticsService.getAccessTrendStatistics(documentId, days);
    }

    @Override
    public Integer cleanupExpiredStatistics(Integer days) {
        return documentStatisticsService.cleanupExpiredStatistics(days);
    }

    @Override
    public Boolean incrementDownloadCount(String documentId, String userId) {
        return documentStatisticsService.incrementDownloadCount(documentId, userId);
    }

    @Override
    public Boolean incrementViewCount(String documentId, String userId) {
        return documentStatisticsService.incrementViewCount(documentId, userId);
    }

    @Override
    public Boolean incrementFavoriteCount(String documentId, String userId) {
        return documentStatisticsService.incrementFavoriteCount(documentId, userId);
    }

    @Override
    public Boolean decrementFavoriteCount(String documentId, String userId) {
        return documentStatisticsService.decrementFavoriteCount(documentId, userId);
    }

    @Override
    public Boolean updateDocumentRating(String documentId, String userId, Double rating) {
        return documentStatisticsService.updateDocumentRating(documentId, userId, rating);
    }
}
